# This file is sourced by init.sh, *before* its initialization.

# This goes hand in hand with the "9>&2;" in tests/Makefile.am's
# TESTS_ENVIRONMENT definition.
stderr_fileno_=9

# Map settings of "none" to the empty string.
test _"$LOCALE_FR" = _none && LOCALE_FR=
test _"$LOCALE_FR_UTF8" = _none && LOCALE_FR_UTF8=

# Unset key environment variables.
if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
  as_unset=unset
else
  as_unset=false
fi

# Derive this list by searching for string literals as the first
# argument to getenv:
# git grep getenv|perl -nle '/\bgetenv *\("(.+?)"\)/ and print $1'|sort -u grep
vars_='
GREP_COLOR
GREP_COLORS
TERM
'
envvar_check_fail=0
for v_ in $vars_
do
  $as_unset $v_
  if eval test \"\${$v_+set}\" = set; then
    echo "$0: the $v_ environment variable is set --" \
      ' unset it and rerun this test' >&2
    envvar_check_fail=1
  fi
done

test "$envvar_check_fail" = 1 && fail_ "failed to unset the above envvars"

require_timeout_()
{
  ( timeout 10s true ) > /dev/null 2>&1 \
    || skip_ your system lacks the timeout program
  returns_ 1 timeout 10s false \
    || skip_ your system has a non-GNU timeout program
  returns_ 124 timeout 0.01 sleep 0.02 \
    || skip_ "'timeout 0.01 sleep 0.02' did not time out"
}

require_pcre_()
{
  echo . | grep -P . 2>err || {
    test $? -eq 1 && fail_ PCRE available, but does not work.
    skip_ no PCRE support
  }
  compare /dev/null err || fail_ PCRE available, but stderr not empty.
}

# Some tests would fail without this particular locale.
# If the locale is not available, just skip the test.
require_en_utf8_locale_()
{
  path_prepend_ .
  case $(get-mb-cur-max en_US.UTF-8) in
    [3456]) ;;
    *) skip_ 'en_US.UTF-8 locale not found' ;;
  esac
}

require_tr_utf8_locale_()
{
  path_prepend_ .
  case $(get-mb-cur-max tr_TR.UTF-8) in
    [3456]) ;;
    *) skip_ 'tr_TR.UTF-8 locale not found' ;;
  esac
}

require_ru_RU_koi8_r()
{
  path_prepend_ .
  case $(get-mb-cur-max ru_RU.KOI8-R) in
    1) ;;
    *) skip_ 'ru_RU.KOI8-R locale not found' ;;
  esac
}

require_compiled_in_MB_support()
{
  require_en_utf8_locale_
  printf 'é' | LC_ALL=en_US.UTF-8 grep '[[:lower:]]' \
    || skip_ this test requires MBS support
}

require_unibyte_locale()
{
  path_prepend_ .
  for loc in C en_US; do
    for encoding in '' .iso88591 .iso885915 .ISO8859-1 .ISO8859-15; do
      locale=$loc$encoding
      MB_CUR_MAX=$(get-mb-cur-max $locale 2>/dev/null) &&
        test "$MB_CUR_MAX" -eq 1 &&
        LC_ALL=$locale &&
        export LC_ALL &&
        return
    done
  done
  skip_ 'no unibyte locale found'
}

# Define hi_res_time_ to a function that prints the current time
# as a floating point number with greater than 1-second resolution.
# Otherwise, skip the requiring test.
require_hi_res_time_()
{
  local cmd
  for cmd in 'date +%s.%N' \
          'perl -le "use Time::HiRes qw(time); print scalar time()"'; do
      case $($cmd) in
          *.[0-9]*) eval 'hi_res_time_() { '"$cmd"'; }'; break;;
      esac
  done
  type hi_res_time_ || skip_ no high-resolution timer support
}

require_JP_EUC_locale_()
{
  local locale=ja_JP.eucJP
  path_prepend_ .
  case $(get-mb-cur-max $locale) in
    [23])
        LC_ALL=$locale &&
        export LC_ALL &&
        return
        ;;
    *) ;;
  esac

  skip_ "$locale locale not found"
}

expensive_()
{
  if test "$RUN_EXPENSIVE_TESTS" != yes; then
    skip_ 'expensive: disabled by default
This test is relatively expensive, so it is disabled by default.
To run it anyway, rerun make check with the RUN_EXPENSIVE_TESTS
environment variable set to yes.  E.g.,

  env RUN_EXPENSIVE_TESTS=yes make check

or use the shortcut target of the toplevel Makefile,

  make check-expensive
'
  fi
}

# Like printf with a single argument, but that argument must be a
# sequence of four-byte strings \xHH where each H is a hexadecimal byte.
hex_printf_()
{
  local octal_fmt=$(printf '\\%o' \
    $(printf '%s\n' "$1" \
      | sed 's,\\x\([0-9abcdefABCDEF][0-9abcdefABCDEF]\), 0x\1,g'))
  printf "$octal_fmt"
}

# Wrap tr so that it always runs in the C locale.
# Otherwise, in a multibyte locale, GNU tr (which is not multibyte-aware
# as of 2014-11-08), would work differently than others.  For example,
# this command, which was written with unibyte GNU tr in mind,
#   LC_ALL=ja_JP.eucJP tr AB '\244\263'
# would act like this with the multibyte tr from HP-UX and Solaris:
#   LC_ALL=ja_JP.eucJP tr A  '\244\263'
tr() { LC_ALL=C env -- tr "$@"; }

# Usage: user_time_ EXPECTED_EXIT_STATUS CMD ...
# If CMD ... exits with the expected exit status, print the elapsed
# child "user" time (not "system" time) in milliseconds and return 0.
# Otherwise, diagnose the exit status mismatch and return nonzero.
user_time_()
{
  $PERL -le '
    my $expected_exit_status = $ARGV[0];
    shift @ARGV;

    system (@ARGV);
    my ($user, $system, $child_user, $child_system) = times;

    my $me = q('"$ME_"');
    $? == -1
      and die qq($me: failed to exec ") . join (" ", @ARGV) . qq(": $!\n);
    my $rc = $?;
    my $sig = ($rc & 127);
    $sig and die "$me: child died with signal $sig\n";
    $rc >>= 8;
    $rc == $expected_exit_status
      or die "$me: bad exit status: expected $expected_exit_status; got $rc\n";

    # Print milliseconds of child user time.
    $child_user *= 1000;
    print int ($child_user + 0.5)' "$@"
}

# yes is not portable, fake it with $AWK
yes() { line=${*-y} ${AWK-awk} 'BEGIN{for (;;) print ENVIRON["line"]}'; }
